home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / comm / dnet / dnet_213 / part03 < prev    next >
Internet Message Format  |  1990-03-27  |  64KB

  1. Path: xanth!cs.odu.edu!Amiga-Request
  2. From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v90i120: DNet 2.13 - multiple windows/file transfers over a serial line, Part03/08
  5. Message-ID: <11940@xanth.cs.odu.edu>
  6. Date: 27 Mar 90 01:19:14 GMT
  7. Sender: tadguy@cs.odu.edu
  8. Reply-To: dales%teksce.sce.tek.com@RELAY.CS.NET
  9. Lines: 2477
  10. Approved: tadguy@cs.odu.edu (Tad Guy)
  11. X-Mail-Submissions-To: Amiga@cs.odu.edu
  12. X-Post-Discussions-To: comp.sys.amiga
  13.  
  14. Submitted-by: dales%teksce.sce.tek.com@RELAY.CS.NET
  15. Posting-number: Volume 90, Issue 120
  16. Archive-name: comm/dnet/dnet-2.13/part03
  17.  
  18. #!/bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of archive 3 (of 8)."
  25. # Contents:  amiga/INSTALLATION amiga/README amiga/client/putfiles.c
  26. #   amiga/dnet/ipc.c amiga/doc/dnetlib.doc amiga/doshand/dos.h
  27. #   amiga/server/scopy.c unix/README unix/client/putfiles.c
  28. #   unix/dnet/internal.c unix/doc/dnetlib.doc unix/server/sgcopy.c
  29. # Wrapped by tadguy@xanth on Mon Mar 26 20:15:11 1990
  30. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  31. if test -f 'amiga/INSTALLATION' -a "${1}" != "-c" ; then 
  32.   echo shar: Will not clobber existing file \"'amiga/INSTALLATION'\"
  33. else
  34. echo shar: Extracting \"'amiga/INSTALLATION'\" \(4800 characters\)
  35. sed "s/^X//" >'amiga/INSTALLATION' <<'END_OF_FILE'
  36. X
  37. X            BASIC INSTALLATION AND RUN
  38. X
  39. X               --- AMIGA INSTALL ---
  40. X
  41. X    The 1.3 (or greater) serial.device must be used
  42. X
  43. X    The following must exist in L: and be mounted.
  44. X
  45. X    L:NULL-HANDLER
  46. X    L:DPIPE-HANDLER (only required if you use the remote cli server)
  47. X
  48. X
  49. X    The following must exist in S:
  50. X
  51. X    S:DNET.SERVERS
  52. X    S:DNET.CONFIG
  53. X
  54. X    You may have to modify S:DNET.CONFIG to appropriately handle the
  55. X    CONNECT message of your modem.
  56. X
  57. X    If you do not have a logical DNET: assignment where the server
  58. X    executables are in DNET:AMIGA/BIN then you must modify S:DNET.SERVERS
  59. X    to point to the appropriate server executables.
  60. X
  61. X    Make sure your path includes DNET:AMIGA/BIN or wherever you have placed
  62. X    the client executables.  This is required so DNET knows how to find
  63. X    the FTERM executable when starting up the automatic FTERM.
  64. X
  65. X
  66. X            --- UNIX INSTALL ---
  67. X
  68. X    You must set the enviroment variable DNETDIR in your .cshrc to an
  69. X    initially empty directory (i.e. create an unobstrusive directory).  This
  70. X    directory will hold the UNIX domain sockets DNet uses to communicate.
  71. X    Security on the UNIX side is solely determined by who has access to this
  72. X    directory.    For example:
  73. X
  74. X    Extract the distribution.
  75. X
  76. X    % cd dnet
  77. X    % MAKE        (you may have to chmod this +x, this is a shell script)
  78. X
  79. X    This compiles the code.  Binaries should exist in dnet/unix/bin.  If
  80. X    you have problems not easily fixed please email me.  Note that the
  81. X    source only compiles on systems compatible with BSD 4.3 .  The code
  82. X    should compile on Suns running 3.5 but does not appear to run on
  83. X    suns running 4.0 (??).  The code compiles and runs on Dynix system
  84. X    3.0.12 or higher.  The code has been found to compile pretty well
  85. X    on Sys V *with* berkeley socket extensions.
  86. X
  87. X    % cd ~
  88. X    % mkdir .DNET
  89. X    % vi .cshrc     (and add the following line)
  90. X    setenv DNETDIR ~/.DNET/
  91. X    % source .cshrc    (make sure the change is made part of your shell)
  92. X
  93. X    NOTE the trailing slash (/) on the DNETDIR enviroment variable.  Do
  94. X    not forget this.
  95. X
  96. X    Copy the UNIX dnet.servers file into ~/.DNET (or whatever directory
  97. X    you had defined from DNETDIR.
  98. X
  99. X
  100. X            ******** RUN *******
  101. X
  102. X    Sequence of events (basic options, see dnet.doc for other options).
  103. X    2400 baud is assumed in the below example, simply change where it
  104. X    applies if running at a different baud rate.
  105. X
  106. X    (1) on amiga
  107. X
  108. X        (i) The connection to your system is 7 bits and parity is
  109. X        ignored.
  110. X
  111. X            1> run dnet -b2400 -P0 -Z0
  112. X
  113. X        (ii) The connection to your system is 7 bits even parity and
  114. X        parity is enforced.
  115. X
  116. X            1> run DNET -b2400 -P0 -Z2
  117. X
  118. X        (iii) The connection to your system is 8 bits and supports raw
  119. X        8 bit transfers (no parity).
  120. X
  121. X            1> run DNET -b2400 -P0 -Z0 -m0
  122. X
  123. X        Other combinations may apply, see doc/dnet.doc for details. The
  124. X        -P option selects the protocol and -Z selects parity.
  125. X
  126. X    (2) From small DNet window now open on the amiga.
  127. X
  128. X        Use the AT command set or otherwise instruct your modem to
  129. X        dial your system.  For hard connections where no modem exists
  130. X        this is not necessary, though with some hard connections you
  131. X        will need to use the SEND-BREAK menu option to send a line
  132. X        break to get a system prompt.
  133. X
  134. X        Log into your UNIX account
  135. X
  136. X    (3) From the UNIX prompt:   (be sure the DNETDIR enviroment variable
  137. X        is set appropriately and your path contains the dnet executable
  138. X        and clients.
  139. X
  140. X        (i) The connection to your system is 7 bits and parity is ignored,
  141. X
  142. X            % dnet
  143. X
  144. X        (ii) The connection to your system is 7 bits even parity and parity
  145. X        is enforced
  146. X
  147. X            % stty -odd
  148. X            % dnet
  149. X
  150. X        (iii) The connection to your system is 8 bits
  151. X
  152. X            % dnet -m0
  153. X
  154. X    (4) At this point the small dnet window should disappear.  After a
  155. X        few seconds an FTERM window should open and after another small
  156. X        delay give you a shell prompt.
  157. X
  158. X        Congratulations, you are running DNet.
  159. X
  160. X        Now you may do all sorts of things.  You may run other FTERM
  161. X        windows from your amiga (1> run fterm) and therefore have
  162. X        several shell windows... you can run file transfer clients
  163. X        (putfiles and getfiles) on either the amiga or unix sides, etc...
  164. X        read the documentation in the doc directory for more info.
  165. X
  166. X
  167. X                SHUTTING DOWN
  168. X
  169. X    Logging out of an FTERM window does not kill DNet.  To kill DNet
  170. X    use the 'quitdnet' command on the Amiga side.  This should kill all
  171. X    connections and bring back the original small dnet window with the
  172. X    original shell prompt from which you should be able to log out
  173. X    normally.  If you are unable to get the original shell prompt in
  174. X    the small dnet window you may have to restart the protocol (menu
  175. X    option) and try 'quitdnet' again.  If all else fails simply hanging
  176. X    up the modem should work (in which case you BREAK the dnet process
  177. X    on the Amiga side).
  178. X
  179. X
  180. X
  181. X
  182. END_OF_FILE
  183. if test 4800 -ne `wc -c <'amiga/INSTALLATION'`; then
  184.     echo shar: \"'amiga/INSTALLATION'\" unpacked with wrong size!
  185. fi
  186. # end of 'amiga/INSTALLATION'
  187. fi
  188. if test -f 'amiga/README' -a "${1}" != "-c" ; then 
  189.   echo shar: Will not clobber existing file \"'amiga/README'\"
  190. else
  191. echo shar: Extracting \"'amiga/README'\" \(5722 characters\)
  192. sed "s/^X//" >'amiga/README' <<'END_OF_FILE'
  193. X
  194. X                  DNET V2.10
  195. X                27 November 1989
  196. X
  197. X    NEW THIS RELEASE:   7 bit support.
  198. X
  199. X    DNET (c)Copyright 1987-1989 Matthew Dillon, All Rights Reserved
  200. X
  201. X    Matthew Dillon
  202. X    891 Regal Rd
  203. X    Berkeley, Ca. 94708
  204. X    USA
  205. X
  206. X    ...!ihnp4!ucbvax!dillon     USENET
  207. X    dillon@ucbvax.Berkeley.edu    ARPANET
  208. X    ucbvax.berkeley.edu pub/amiga    ARPANET-FTP
  209. X
  210. X                   WHAT IS DNET
  211. X
  212. X    DNet is a link protocol and should properly be called DLink, but
  213. X the name DNet stuck and so it will stay.  DNet allows one to connect two
  214. X amigas together and run multiple connections between them.  For example,
  215. Xyou can open a talk window or two or three and be doing an upload and be
  216. Xdoing a download all at the same time.
  217. X
  218. X    Currently, DNet can be used to connect two Amiga's together or
  219. Xan Amiga to a 4.2BSD/4.3BSD compatible UNIX.
  220. X
  221. X    ** AN 8 BIT PATH IS NO LONGER REQUIRED.  DNET WILL NOW RUN OVER
  222. X    7 BIT PATHS.  (TAB,FF,CR,LF, 0x20-0x7F).
  223. X
  224. X
  225. X              INSTALLING DNET ON YOUR AMIGA
  226. X
  227. X    (1) ## REMOVED, was copy dres.library to libs:.  no longer required.
  228. X
  229. X    (2) copy the DNet binary and all client and server program to
  230. X        somewhere accessable on your path.
  231. X
  232. X    (3) copy s/dnet.servers to s:
  233. X
  234. X        * modify s:dnet.servers so all server paths point to whereever
  235. X          you stuck the servers
  236. X
  237. X    (4) copy s/dnet.config  to s:
  238. X
  239. X        * you may have to modify s:dnet.config too ... look into the
  240. X          DOC directory for more information.
  241. X
  242. X              CALL A FRIEND WHO HAS GOT DNET INSTALLED
  243. X
  244. X    1> RUN DNET -X -8 -b1200
  245. X
  246. X    NOTE:  -h0 option in previous versions is now the default.  Use -h1
  247. X           to *enable* carrier detect checking.
  248. X
  249. X           7 bit mode is now the default.  Use -m0 if you have an 8 bit
  250. X           connection and want to take advantage of it.
  251. X
  252. X    PARITY NOTE:  If your system forces parity you specify the
  253. X            appropriate parity option with the -Z switch,
  254. X            refer to dnet.doc
  255. X
  256. X    warning: The defaults for -X (manual mode) in S:DNET.CONFIG
  257. X    turn off security.  Please read documentation in the doc directory
  258. X    for more information.  This README file is only intended to get
  259. X    you up and running.  The above line also sets the baud to 1200...
  260. X    the idea is you set it to what is proper for your modem.  Again,
  261. X    read DOC/DNET.DOC for more options and information.
  262. X
  263. X    A small DNET window should appear from which you can dialup your
  264. X    friend's amiga.  On CONNECT, DNET should automatically adjust the
  265. X    baud rate.  It may be necessary to modify S:DNET.CONFIG in this
  266. X    regard (read the docs!)
  267. X
  268. X    After connecting, executing the START DNET menu option from either
  269. X    end will start the protocol.  The small dnet window should go away
  270. X    and DNET should attempt to run the FTERM client program, which
  271. X    connects to an STERM server program on the other end.  Your friend's
  272. X    amiga will do the same.
  273. X
  274. X    If all goes ok, it should flash the window size in the title bar
  275. X    and you can type.  If not, the window will go away and an error
  276. X    message will be printed out in your CLI: "unable to connect".
  277. X
  278. X    WARNING:    Even if there are no windows open (no clients active),
  279. X    DNet is still running!!!!  us the CLI BREAK command to kill DNet
  280. X    and give you back the initial DNet window, from which you can
  281. X    hit the close-window gadget.
  282. X
  283. X    breaking the DNet protocol will kill any active clients.
  284. X
  285. X
  286. X                SERVERS AND CLIENTS
  287. X
  288. X
  289. X    DNet has a notion of servers and clients.  That is, you run the
  290. Xprotocol as described above, then run other external programs that talk
  291. Xto the core program "DNet".  These other external programs "FTerm",
  292. X"GetFiles", "PutFiles", etc... obtain virtual connections to special
  293. Xserver programs on the remote machine.
  294. X
  295. X    Thus, when you started the protocol above DNet automatically
  296. Xran the FTERM client... you can run as many FTERMs as you have memory
  297. Xfor (well, actually, DNet is limited to 64 simultanious channels).  When
  298. Xa client program such as FTERM is run on computer A, it causes the
  299. Xappropriate server program (STERM in this case) to automatically be run
  300. Xon computer B.    The client and server need some way to rendezvous, and they
  301. Xdo this by giving the same PORT NUMBER to the protocol driver.
  302. X
  303. X    This is what the S:DNET.SERVERS file is ... when you run a client
  304. Xon computer A it asks for server #<blah> (e.g. 8195 for an FTERM) on the
  305. Xremote machine.  computer B (the remote machine) looks up 8195 in the
  306. XS:DNET.SERVERS file, finds the path to the server in question, and runs it
  307. Xautomatically.
  308. X
  309. X    PORT    CLIENT    SERVER        PURPOSE
  310. X
  311. X    8192    PutFiles    SCopy        send files to remote computer
  312. X    8195    FTerm    STerm        open a talk window on both computers
  313. X    8196    CLITerm    SCli        remote-CLI (actually newshell)
  314. X    8197    LoadAv    ------        Load-Average window (when running DNet
  315. X                    to a UNIX machine)
  316. X    8198    ------    SPrint        printer server
  317. X    8199    ------    SPasswd     password server.  Used to gain security
  318. X                    access for auto-answer callups
  319. X    8201    GetFiles    SGCopy        download files from remote computer
  320. X
  321. X    NOTE: FTERM may be used to connect to arbitrary ports that otherwise have
  322. X    no associated client.  see the docs for FTERM.
  323. X
  324. X        READ THE DOCS FOR EACH OF THESE CLIENTS
  325. X
  326. X                   SECURITY
  327. X
  328. X    Read DOC/DNET.DOC and documentation for each client/server.  DNet
  329. X    implements various levels of security.  This is intended for BBS
  330. X    support but I have not finished my DNet-BBS program yet.  The security
  331. X    is still there, however.
  332. X
  333. X    One example:    If the DNET_READ security option (env: var is set
  334. X    automatically from S:DNET.CONFIG depending on the option you give
  335. X    DNET when you first run it) is anything less than 9, the SGCopy
  336. X    server for GetFiles will only allow uploading from directories with
  337. X    their comment field set a certain way.  That is, you can control
  338. X    exactly what you allow other people to download.
  339. X
  340. X
  341. X
  342. END_OF_FILE
  343. if test 5722 -ne `wc -c <'amiga/README'`; then
  344.     echo shar: \"'amiga/README'\" unpacked with wrong size!
  345. fi
  346. # end of 'amiga/README'
  347. fi
  348. if test -f 'amiga/client/putfiles.c' -a "${1}" != "-c" ; then 
  349.   echo shar: Will not clobber existing file \"'amiga/client/putfiles.c'\"
  350. else
  351. echo shar: Extracting \"'amiga/client/putfiles.c'\" \(3861 characters\)
  352. sed "s/^X//" >'amiga/client/putfiles.c' <<'END_OF_FILE'
  353. X
  354. X/*
  355. X *  PUTFILES.C
  356. X *
  357. X *  DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
  358. X *
  359. X *  Upload one or more files or directories to the remote host
  360. X */
  361. X
  362. X#include "defs.h"
  363. X
  364. Xchar Buf[1024];
  365. X
  366. Xint putname ARGS((void *, char *));
  367. Xint putfile ARGS((void *, char *, char *));
  368. Xint writehdr ARGS((void *, ubyte, char *, long));
  369. X
  370. Xvoid main ARGS((int, char **));
  371. X
  372. Xint
  373. Xbrk()
  374. X{
  375. X    return(0);
  376. X}
  377. X
  378. Xvoid
  379. Xmain(ac,av)
  380. Xchar *av[];
  381. X{
  382. X    void *chan;
  383. X    short i;
  384. X    char fn = 0;
  385. X    char *host = NULL;
  386. X    char *dir = NULL;
  387. X
  388. X    printf("PutFiles V%s%s\n", VERSION, PUTFILES_VERSION);
  389. X    ac = DoOption(ac, av, "N%sd%s", &host, &dir);
  390. X
  391. X    onbreak(brk);
  392. X    if (ac <= 1) {
  393. X    puts("putfiles [-Nnetid] [-dremotedir] file/dir file/dir ....");
  394. X    exit(1);
  395. X    }
  396. X    chan = DOpen(host, PORT_FILECOPY, -80, 126);
  397. X    if (!chan) {
  398. X    puts("Unable to connect");
  399. X    exit(1);
  400. X    }
  401. X    DRead(chan, &fn, 1);
  402. X    if (fn == 'S') {
  403. X    puts("Remote Server Permission Denied");
  404. X    DClose(chan);
  405. X    exit(1);
  406. X    }
  407. X    if (fn != 'Y') {
  408. X    puts("Remote Server Software Error");
  409. X    DClose(chan);
  410. X    exit(1);
  411. X    }
  412. X    if (dir) {
  413. X    if (writehdr(chan, 'C', dir, 0) != 'Y') {
  414. X        printf("Remote directory unavailable: %s\n", dir);
  415. X        goto fail;
  416. X    }
  417. X    }
  418. X    for (i = 1; i < ac; ++i) {
  419. X    if (putname(chan, av[i]) < 0)
  420. X        break;
  421. X    }
  422. Xfail:
  423. X    printf("\nclosing... ");
  424. X    fflush(stdout);
  425. X    DClose(chan);
  426. X    puts("done");
  427. X}
  428. X
  429. Xint
  430. Xputname(chan, file)
  431. Xvoid *chan;
  432. Xchar *file;
  433. X{
  434. X    long lock = Lock(file, SHARED_LOCK);
  435. X    long dirl;
  436. X    int ret = 1;
  437. X    FIB *fib = (FIB *)malloc(sizeof(FIB));
  438. X
  439. X    printf("%-20s ", file);
  440. X    if (lock == NULL || !Examine(lock, fib)) {
  441. X    if (lock)
  442. X        UnLock(lock);
  443. X    free(fib);
  444. X    puts("NOT FOUND");
  445. X    return(1);
  446. X    }
  447. X    if (fib->fib_DirEntryType > 0) {
  448. X    char *dirname = (fib->fib_FileName[0]) ? fib->fib_FileName : "ram";
  449. X    puts("DIR");
  450. X    dirl = (long)CurrentDir(lock);
  451. X    if (writehdr(chan, 'X', dirname, 0) != 'Y') {
  452. X        puts("Remote unable to make directory");
  453. X        goto f1;
  454. X    }
  455. X    while (ExNext(lock, fib)) {
  456. X        if (putname(chan, fib->fib_FileName) < 0) {
  457. X        ret = -1;
  458. X        goto f1;
  459. X        }
  460. X    }
  461. X    writehdr(chan, 'Y', "?", 0);
  462. Xf1:
  463. X    UnLock(CurrentDir(dirl));
  464. X    } else {
  465. X    UnLock(lock);
  466. X    ret = putfile(chan, file, fib->fib_FileName);
  467. X    }
  468. X    free(fib);
  469. X    return(ret);
  470. X}
  471. X
  472. Xint
  473. Xputfile(chan, file, stripedname)
  474. Xvoid *chan;
  475. Xchar *file;
  476. Xchar *stripedname;
  477. X{
  478. X    long fh = (long)Open(file, 1005);
  479. X    long n, r, len;
  480. X    long ttl = 0;
  481. X    char co;
  482. X
  483. X    fflush(stdout);
  484. X    if (fh == NULL) {
  485. X    puts("FILE NOT FOUND");
  486. X    return(0);
  487. X    }
  488. X    Seek(fh, 0, 1);                 /*  get length */
  489. X    len = ttl = Seek(fh, 0, -1);
  490. X    if (writehdr(chan, 'W', stripedname, len) != 'Y') {
  491. X    puts("REMOTE UNABLE TO ACCEPT FILE");
  492. X    Close(fh);
  493. X    return(0);
  494. X    }
  495. X    printf("%6ld/%-6ld", ttl - len, ttl);
  496. X    while (len) {
  497. X    fflush(stdout);
  498. X    r = (len > sizeof(Buf)) ? sizeof(Buf) : len;
  499. X    n = Read(fh, Buf, r);
  500. X    if (n != r) {
  501. X        puts("Local File error");
  502. X        Close(fh);
  503. X        return(-1);
  504. X    }
  505. X    if (DWrite(chan, Buf, n) != n) {
  506. X        puts("Remote error");
  507. X        Close(fh);
  508. X        return(-1);
  509. X    }
  510. X    if (SetSignal(0,0) & (SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D)) {
  511. X        puts("\nBreak");
  512. X        Close(fh);
  513. X        return(-1);
  514. X    }
  515. X    len -= n;
  516. X    printf("\010\010\010\010\010\010\010\010\010\010\010\010\010");
  517. X    printf("%6ld/%-6ld", ttl - len, ttl);
  518. X    }
  519. X    Close(fh);
  520. X    printf("Queued, waiting...");
  521. X    fflush(stdout);
  522. X    DRead(chan, &co, 1);
  523. X    if (co != 'Y') {
  524. X    puts("Remote Server Software Error");
  525. X    return(-1);
  526. X    }
  527. X    puts("  OK");
  528. X    return(0);
  529. X}
  530. X
  531. Xint
  532. Xwritehdr(chan, c, name, len)
  533. Xvoid *chan;
  534. Xunsigned char c;
  535. Xchar *name;
  536. Xlong len;
  537. X{
  538. X    if (DWrite(chan, &c, 1) != 1)
  539. X    return(-1);
  540. X    c = strlen(name) + 1;
  541. X    if (DWrite(chan, &c, 1) != 1)
  542. X    return(-1);
  543. X    if (DWrite(chan, name, c) != c)
  544. X    return(-1);
  545. X    if (DWrite(chan, &len, 4) != 4)
  546. X    return(-1);
  547. X    if (DRead(chan, &c, 1) == 1)
  548. X    return((int)c);
  549. X    return(-1);
  550. X}
  551. X
  552. END_OF_FILE
  553. if test 3861 -ne `wc -c <'amiga/client/putfiles.c'`; then
  554.     echo shar: \"'amiga/client/putfiles.c'\" unpacked with wrong size!
  555. fi
  556. # end of 'amiga/client/putfiles.c'
  557. fi
  558. if test -f 'amiga/dnet/ipc.c' -a "${1}" != "-c" ; then 
  559.   echo shar: Will not clobber existing file \"'amiga/dnet/ipc.c'\"
  560. else
  561. echo shar: Extracting \"'amiga/dnet/ipc.c'\" \(4430 characters\)
  562. sed "s/^X//" >'amiga/dnet/ipc.c' <<'END_OF_FILE'
  563. X
  564. X/*
  565. X *  IPC.C
  566. X *
  567. X *  Handle IPC messages
  568. X *
  569. X *  NOTE:   Only an explicit disconnect command will drop DTR, or when
  570. X *        the serial.device is closed.
  571. X */
  572. X
  573. Xstatic int dummy;
  574. X
  575. X#ifdef NOTDEF
  576. X
  577. X#include "dnet.h"
  578. X#include <local/ipc.h>
  579. X
  580. X#define IPCMDS struct _IPCMDS
  581. X
  582. Xvoid do_online(), do_offline(), do_stat(), do_quit(), do_disconnect();
  583. Xvoid do_state();
  584. Xvoid do_recvon(), do_recvoff(), do_serialon(), do_serialoff();
  585. Xvoid do_baud();
  586. Xvoid do_getidle(), do_getconnect(), do_setidlealert(), do_setconnectalert();
  587. Xvoid do_lessconnect(), do_resetconnect(), do_resetidle();
  588. X
  589. XIPCMDS {
  590. X    short args;
  591. X    char *name;
  592. X    void (*func)();
  593. X};
  594. X
  595. XIPCMDS IPCmds[] = {
  596. X    0, "online" , do_online,
  597. X    0, "offline", do_offline,
  598. X    0, "stat", do_stat,
  599. X    0, "quit", do_quit,
  600. X    0, "disconnect", do_disconnect,
  601. X    0, "state", do_state,
  602. X    0, "recvon", do_recvon,
  603. X    0, "recvoff", do_recvoff,
  604. X    0, "serialon", do_serialon,
  605. X    0, "serialoff", do_serialoff,
  606. X    1, "baud", do_baud,
  607. X
  608. X    0, "getidle", do_getidle,
  609. X    0, "getconn", do_getconnect,
  610. X    2, "setidlealert", do_setidlealert,
  611. X    2, "setconnalert", do_setconnectalert,
  612. X    1, "lessconn", do_lessconnect,
  613. X    0, "resetconn", do_resetconnect,
  614. X    0, "resetidle", do_resetidle
  615. X};
  616. X
  617. Xhandle_ipc()
  618. X{
  619. X    IPCMSG *msg;
  620. X    char *ptr;
  621. X
  622. X    while (msg = GetMsg(IPCPort)) {
  623. X    long error = IF_ERROR;
  624. X    char **av = NULL;
  625. X    short ac = 0;
  626. X    short i;
  627. X    char *buf = NULL;
  628. X    long len = 0;
  629. X
  630. X    if (ptr = (char *)msg->TBuf) {
  631. X        short networknum = atoi(ptr);
  632. X        if (networknum == NetworkNum) {
  633. X        while (*ptr++);
  634. X        ac = ParseCmd(ptr, &av, NULL, NULL, &error, NULL);
  635. X        } else {
  636. X        error = IF_NOTFND;
  637. X        }
  638. X    }
  639. X    for (i = 0; i < ac;) {
  640. X        IPCMDS *cmds;
  641. X
  642. X        for (cmds = IPCmds; cmds != ARYEND(IPCmds); ++cmds) {
  643. X        if (strcmp(av[i], cmds->name) == 0)
  644. X            break;
  645. X        }
  646. X        if (cmds == ARYEND(IPCmds)) {
  647. X        error = IF_ERROR;
  648. X        break;
  649. X        }
  650. X        if (i + cmds->args >= ac) {
  651. X        error = IF_ERROR;
  652. X        break;
  653. X        }
  654. X        error = 0;
  655. X        (*cmds->func)(av + i, &buf, &len);
  656. X        i += cmds->args + 1;
  657. X    }
  658. X    if (av)
  659. X        FreeParseCmd(av);
  660. X    ReplyIPC(msg, buf, len, error);
  661. X    }
  662. X}
  663. X
  664. Xvoid
  665. Xdo_online()
  666. X{
  667. X    OnLine = 1;
  668. X}
  669. X
  670. Xvoid
  671. Xdo_offline()
  672. X{
  673. X    OnLine = 0;     /*    Take DNet off line  */
  674. X}
  675. X
  676. Xvoid
  677. Xdo_disconnect()
  678. X{
  679. X    OnLine = 0;     /*    Take DNet off line  */
  680. X    DropDTR();      /*  and (temp) drop DTR */
  681. X}
  682. X
  683. Xvoid
  684. Xdo_quit()
  685. X{
  686. X    Quit = 1;        /*    Quit out of dnet    */
  687. X}
  688. X
  689. Xvoid
  690. Xdo_stat(av, pbuf, plen)
  691. Xchar **pbuf;
  692. Xlong *plen;
  693. X{
  694. X    char buf[256];
  695. X    char *ptr = buf;
  696. X
  697. X    sprintf(ptr, "         Bytes  Packets   Errors\n");
  698. X    ptr += strlen(ptr);
  699. X    sprintf(ptr, "OUT:  %8ld %8ld %8ld\n", BytesOut, PacketsOut, PacketsResent);
  700. X    ptr += strlen(ptr);
  701. X    sprintf(ptr, "IN :  %8ld %8ld %8ld\n", BytesIn, PacketsIn, PacketsNakd);
  702. X    ptr += strlen(ptr);
  703. X    sprintf(ptr, "Garbage Bytes In: %ld\n", GarbageIn);
  704. X    ptr += strlen(ptr);
  705. X    if (ptr - buf > sizeof(buf))
  706. X    dneterror("do_stat: buffer overrun");
  707. X    AllocAppend(pbuf, plen, buf, strlen(buf)+1);
  708. X}
  709. X
  710. X/*
  711. X *  Return machine state (ascii)
  712. X *
  713. X *  s iiii:ii oooo:oo        (s = 0/1 1=protrunning
  714. X *                 i = idle time hrs:min
  715. X *                 o = online time hrs:min
  716. X */
  717. X
  718. Xvoid
  719. Xdo_state()
  720. X{
  721. X
  722. X}
  723. X
  724. XAllocAppend(pbuf, plen, buf, len)
  725. Xchar **pbuf;
  726. Xlong *plen;
  727. Xchar *buf;
  728. Xlong len;
  729. X{
  730. X    char *new;
  731. X    if (*pbuf) {
  732. X    new = malloc(*plen + len);
  733. X    BMov(*pbuf, new, *plen);
  734. X    free(*pbuf);
  735. X    *pbuf = new;
  736. X    new += *plen;
  737. X    } else {
  738. X    *pbuf = new = malloc(len);
  739. X    }
  740. X    BMov(buf, new, len);
  741. X    *plen += len;
  742. X}
  743. X
  744. Xvoid
  745. Xdo_recvon()
  746. X{
  747. X    NetRecvOn();
  748. X}
  749. X
  750. Xvoid
  751. Xdo_recvoff()
  752. X{
  753. X    NetRecvOff();
  754. X}
  755. X
  756. Xvoid
  757. Xdo_serialon()
  758. X{
  759. X    NetSerialOn();
  760. X}
  761. X
  762. Xvoid
  763. Xdo_serialoff()
  764. X{
  765. X    NetSerialOff();
  766. X}
  767. X
  768. Xvoid
  769. Xdo_baud(av)
  770. Xchar **av;
  771. X{
  772. X    long baud = atoi(av[1]);
  773. X    if (baud) {
  774. X    Baud = baud;
  775. X    SetBaudRate(baud);
  776. X    }
  777. X}
  778. X
  779. Xvoid
  780. Xdo_getidle(av, pbuf, plen)
  781. Xchar **av;
  782. Xchar **pbuf;
  783. Xlong *plen;
  784. X{
  785. X    char buf[32];
  786. X    sprintf(buf, "%ld", GetIdle());
  787. X    AllocAppend(pbuf, plen, buf, strlen(buf)+1);
  788. X}
  789. X
  790. Xvoid
  791. Xdo_getconnect(av, pbuf, plen)
  792. Xchar **av;
  793. Xchar **pbuf;
  794. Xlong *plen;
  795. X{
  796. X    char buf[32];
  797. X    sprintf(buf, "%ld", GetConnect());
  798. X    AllocAppend(pbuf, plen, buf, strlen(buf)+1);
  799. X}
  800. X
  801. Xvoid
  802. Xdo_setidlealert(av)
  803. Xchar **av;
  804. X{
  805. X    SetIdleAlert(atoi(av[1]), av[2]);
  806. X}
  807. X
  808. Xvoid
  809. Xdo_setconnectalert(av)
  810. Xchar **av;
  811. X{
  812. X    SetConnectAlert(atoi(av[1]), av[2]);
  813. X}
  814. X
  815. Xvoid
  816. Xdo_lessconnect(av)
  817. Xchar **av;
  818. X{
  819. X    LessConnect(atoi(av[1]));
  820. X}
  821. X
  822. Xvoid
  823. Xdo_resetconnect()
  824. X{
  825. X    ResetConnect();
  826. X}
  827. X
  828. Xvoid
  829. Xdo_resetidle()
  830. X{
  831. X    ResetIdle();
  832. X}
  833. X
  834. X#endif
  835. X
  836. X
  837. END_OF_FILE
  838. if test 4430 -ne `wc -c <'amiga/dnet/ipc.c'`; then
  839.     echo shar: \"'amiga/dnet/ipc.c'\" unpacked with wrong size!
  840. fi
  841. # end of 'amiga/dnet/ipc.c'
  842. fi
  843. if test -f 'amiga/doc/dnetlib.doc' -a "${1}" != "-c" ; then 
  844.   echo shar: Will not clobber existing file \"'amiga/doc/dnetlib.doc'\"
  845. else
  846. echo shar: Extracting \"'amiga/doc/dnetlib.doc'\" \(5169 characters\)
  847. sed "s/^X//" >'amiga/doc/dnetlib.doc' <<'END_OF_FILE'
  848. X
  849. X               DNET LINK LIBRARY
  850. X
  851. X    Link with your server's and client programs.
  852. X
  853. X
  854. X    listenport    = DListen(port#)                listen for connections
  855. X    chanport    = DAccept(listenport)           accept a new connection
  856. X          DNAAccept(listenport)         or refuse a new connection
  857. X    chanport    = DOpen(host, port#, txpri, rxpri) open a new channel
  858. X          DPri(chanport, priority)      (not implemented yet)
  859. X        act = DNRead(chanport, buf, bytes)  (see below)
  860. X        act = DRead(chanport, buf, bytes)   (see below)
  861. X        act = DWrite(chanport, buf, bytes)  act = -1 or bytes
  862. X          DEof(chanport)                send eof (amiga<>amiga only)
  863. X          DQueue(chanport, maxq)        set asynchronous queue write
  864. X                        queue size (default 0)
  865. X          DClose(chanport)              close a channel
  866. X          DUnListen(listenport)         stop listening on a channel
  867. X
  868. X          DQuit(host)                   cause remote end to quit out
  869. X                        of the DNET protocol.
  870. X
  871. XGeneral notes:
  872. X    The calls have a notion of ownership.  The task which created
  873. X    the listen port or openned the channel owns it.  Foreign tasks
  874. X    may DAccept() connections on somebody elses listen port (i.e.
  875. X    your server creates a task to handle the accept).  In fact, this
  876. X    is the only way you can spawn off tasks to handle new connections
  877. X    as only the owner of a channel (caller of DAccept()/DOpen()) may
  878. X    use the channel.
  879. X
  880. X    The calls are not extremely efficient at the momement, but since
  881. X    the network, by virtue of being on a serial line, is so slow,
  882. X    it doesn't really matter.
  883. X
  884. X    You are guarenteed a signal will be present whenever there is
  885. X    pending data, even if you only partially read what is available.
  886. X    NOTE that you *will* get signals sometimes even when no data is
  887. X    available, and should thus take into account DNRead() returning
  888. X    0...  Usually DNRead() is used in conjuction with Wait()ing on
  889. X    the signal bit of the channel port.
  890. X
  891. X    DEOF()
  892. X
  893. X    Eof a channel.    Implemented ONLY for the Amiga.  You cannot EOF
  894. X    a channel if running between the Amiga and a UNIX machine.   This
  895. X    is essentially an unsupported call, and you should use DCLose()
  896. X    to close(and send an eof) on a channel.  The network handles it
  897. X    just fine, but the UNIX side has no way of sending an EOF over
  898. X    a socket without closing the socket.
  899. X
  900. X    DLISTEN()
  901. X
  902. X    This call listens on a virtual port # (0-65535) for connections
  903. X    from a remote host.  NULL is returned if the port is already
  904. X    being listened on by somebody else.
  905. X
  906. X    DACCEPT()
  907. X
  908. X    Accepts connections over a virtual port #.  Several connections
  909. X    may be accepted and worked on simultaniously.  NULL is returned if
  910. X    there are no pending connections.  You can WaitPort() on the
  911. X    listenport to wait for new connections, but should note that
  912. X    even after a WaitPort(), DAccept() might return NULL every
  913. X    once in a while.
  914. X
  915. X    DAccept() will set the signal bit associated with the port if
  916. X    further connections are pending.
  917. X
  918. X    DNAACCEPT()
  919. X
  920. X    Don't accept connections over a virtual port #.  If there is a
  921. X    connection pending, it will return an error on the other end.
  922. X    Returns 1 if a connection was refused, 0 if there were no
  923. X    pending connections.
  924. X
  925. X    DUNLISTEN()
  926. X
  927. X    Stop listening on a virtual port #.  Any pending requests are
  928. X    automatically DNAAccept()ed.
  929. X
  930. X    DPRI()
  931. X
  932. X    Set the priority of a channel (-128 lowest to 127 highest).
  933. X    The priority only effects throughput when two or more channels
  934. X    at different priorities are transfering data at the same time.
  935. X
  936. X    Not currently implemented.. priority is what you set in DOpen()
  937. X
  938. X    DNREAD()
  939. X
  940. X    Read data from a channel.  0 is a valid return value, meaning that
  941. X    no data is currently ready to read.  You can WaitPort() on the
  942. X    channel port to wait for data (or EOF).  A negative value is
  943. X    returned on EOF or failure.
  944. X
  945. X    error codes:
  946. X            -1    EOF on channel
  947. X            -2    Remote end CLOSED the channel (not implemented)
  948. X
  949. X    DREAD()
  950. X
  951. X    Read data from a channel.  The number of bytes requested are
  952. X    returned, unless the other end closed it's side in which case
  953. X    fewer than the number of bytes requested will be returned.  That
  954. X    is, this call will BLOCK waiting for data.
  955. X
  956. X    A negative value is returned on EOF or failure.
  957. X
  958. X
  959. X    DWRITE()
  960. X
  961. X    Write data to a channel.  The return value is either the # bytes
  962. X    written, or a negative error code.
  963. X
  964. X            -1    Remote end REOF'd the channel
  965. X            -2    Remote end CLOSED the channel
  966. X
  967. X            note: not much distinction between the two
  968. X            currently.
  969. X
  970. X    DCLOSE()
  971. X
  972. X    Close a channel.
  973. X
  974. X    DOPEN()
  975. X
  976. X    Application side OPEN().... Open a port# on a remote host.  Returns
  977. X    a channel port or NULL.  Two priorities are given.  Each may be
  978. X    in the range (lowest) -127 to 126 (highest) inclusive.  The first
  979. X    priority is for transmitting data client->server, the second
  980. X    for receiving data server->client.
  981. X
  982. X    The host field should be NULL for now.    In future versions, you
  983. X    will be able to run multiple DNET's on your Amiga and this will
  984. X    field will determine which one you are attempting to connect
  985. X    through.
  986. X
  987. X    DQUIT()
  988. X
  989. X    Causes DNET on the remote side to quit out.  If running on a
  990. X    4.2BSD UNIX machine, the DNET will exit.  If running on another
  991. X    Amiga, the DNET will return to terminal-window mode.
  992. X
  993. X    The host has the same definition as for DOpen().
  994. X
  995. X
  996. X
  997. END_OF_FILE
  998. if test 5169 -ne `wc -c <'amiga/doc/dnetlib.doc'`; then
  999.     echo shar: \"'amiga/doc/dnetlib.doc'\" unpacked with wrong size!
  1000. fi
  1001. # end of 'amiga/doc/dnetlib.doc'
  1002. fi
  1003. if test -f 'amiga/doshand/dos.h' -a "${1}" != "-c" ; then 
  1004.   echo shar: Will not clobber existing file \"'amiga/doshand/dos.h'\"
  1005. else
  1006. echo shar: Extracting \"'amiga/doshand/dos.h'\" \(3671 characters\)
  1007. sed "s/^X//" >'amiga/doshand/dos.h' <<'END_OF_FILE'
  1008. X
  1009. X/*
  1010. X *  DOS.H
  1011. X */
  1012. X
  1013. X#include <exec/types.h>
  1014. X#include <local/xmisc.h>
  1015. X#include <libraries/dos.h>
  1016. X#include <libraries/dosextens.h>
  1017. X#include <libraries/filehandler.h>
  1018. X
  1019. X#include <stdio.h>
  1020. X
  1021. X#include "/dnet/dnet.h"
  1022. X#include "/server/servers.h"
  1023. X#include "/dnet/channel.h"
  1024. X#include "/lib/dnetlib.h"
  1025. X
  1026. X#include <stdlib.h>
  1027. X#include <string.h>
  1028. X
  1029. X/*
  1030. X *  ACTIONS which do not exist in dosextens.h but which indeed exist on
  1031. X *  the Amiga.
  1032. X */
  1033. X
  1034. X#define ACTION_OPENRW        1004
  1035. X#define ACTION_OPENOLD        1005
  1036. X#define ACTION_OPENNEW        1006
  1037. X#define ACTION_CLOSE        1007
  1038. X#define ACTION_SEEK        1008
  1039. X#define ACTION_RAWMODE        994
  1040. X#define ACTION_MORECACHE    18
  1041. X#define ACTION_FLUSH        27
  1042. X
  1043. X#define DOS_FALSE   0
  1044. X#define DOS_TRUE    -1
  1045. X
  1046. Xtypedef struct DosPacket    PACKET;
  1047. Xtypedef struct DeviceNode    DEVNODE;
  1048. Xtypedef struct DeviceList    DEVLIST;
  1049. Xtypedef struct DosInfo        DOSINFO;
  1050. Xtypedef struct RootNode     ROOTNODE;
  1051. Xtypedef struct FileHandle    FH;
  1052. Xtypedef struct DateStamp    STAMP;
  1053. Xtypedef struct InfoData     INFODATA;
  1054. Xtypedef struct DosLibrary    DOSLIB;
  1055. Xtypedef struct FileLock     LOCK;
  1056. Xtypedef struct FileInfoBlock    FIB;
  1057. Xtypedef struct Library        LIB;
  1058. X
  1059. X#define FILE_DIR    1
  1060. X#define FILE_FILE   -1
  1061. X
  1062. X#define LOCKLINK    struct _LOCKLINK
  1063. X#define HANDLE        struct _HANDLE
  1064. X
  1065. X/*
  1066. X *  We use this structure to link locks together in a list for internal
  1067. X *  usage.  I could have use the link field in the lock structure as a
  1068. X *  real linked list, but didn't want to have to sequentially search the
  1069. X *  list to remove a node.
  1070. X *
  1071. X *  NOTE:   You CANNOT simply extend the FileLock (LOCK) structure.  Some
  1072. X *  programs assume it is sizeof(LOCK) big and break.  I found this out the
  1073. X *  hard way.
  1074. X */
  1075. X
  1076. XLOCKLINK {
  1077. X    NODE    Node;
  1078. X    LOCK    *Lock;
  1079. X};
  1080. X
  1081. X/*
  1082. X *  OPERATION STRUCTURES
  1083. X */
  1084. X
  1085. Xtypedef struct {
  1086. X    long    DirHandle;        /*  relative to directory (0=root)  */
  1087. X    uword   Modes;        /*  open modes                */
  1088. X} OpOpen;
  1089. X
  1090. Xtypedef struct {
  1091. X    long    Handle;
  1092. X    ulong   Prot;
  1093. X    long    Type;
  1094. X    long    Size;
  1095. X    STAMP   Date;        /*  date stamp    */
  1096. X} RtOpen;
  1097. X
  1098. X
  1099. Xtypedef struct {
  1100. X    long    Handle;        /*  file handle to read from        */
  1101. X    long    Bytes;        /*  # of bytes to read            */
  1102. X} OpRead;
  1103. X
  1104. Xtypedef struct {
  1105. X    long    Bytes;        /*  < 0 == error            */
  1106. X} RtRead;
  1107. X
  1108. Xtypedef struct {
  1109. X    long    Handle;        /*  file handle to read from        */
  1110. X    long    Bytes;        /*  # of bytes to read            */
  1111. X} OpWrite;
  1112. X
  1113. Xtypedef struct {
  1114. X    long    Bytes;        /*  < 0 == error            */
  1115. X} RtWrite;
  1116. X
  1117. Xtypedef struct {
  1118. X    long    Handle;
  1119. X} OpClose;
  1120. X
  1121. Xtypedef struct {
  1122. X    long    Handle;
  1123. X    long    Offset;
  1124. X    long    How;
  1125. X} OpSeek;
  1126. X
  1127. Xtypedef struct {
  1128. X    long    OldOffset;
  1129. X    long    NewOffset;        /*    -1 = error  */
  1130. X} RtSeek;
  1131. X
  1132. Xtypedef struct {
  1133. X    long    Handle;
  1134. X} OpParent;
  1135. X
  1136. Xtypedef RtOpen    RtParent;
  1137. X
  1138. Xtypedef struct {
  1139. X    long    DirHandle;
  1140. X} OpDelete;
  1141. X
  1142. Xtypedef struct {
  1143. X    long    Error;
  1144. X} RtDelete;
  1145. X
  1146. Xtypedef OpDelete OpCreateDir;
  1147. Xtypedef RtParent RtCreateDir;
  1148. X
  1149. Xtypedef struct {
  1150. X    long    Handle;
  1151. X} OpDup;
  1152. X
  1153. Xtypedef RtOpen    RtDup;
  1154. X
  1155. Xtypedef struct {
  1156. X    long    Handle;        /*    oops, actually a directory handle   */
  1157. X    long    Index;
  1158. X} OpNextDir;
  1159. X
  1160. Xtypedef RtOpen    RtNextDir;
  1161. X
  1162. Xtypedef struct {
  1163. X    long    DirHandle1;
  1164. X    long    DirHandle2;
  1165. X} OpRename;
  1166. X
  1167. Xtypedef struct {
  1168. X    long    Error;
  1169. X} RtRename;
  1170. X
  1171. X/*
  1172. X *  Filehandle structure associated with an open file handle
  1173. X */
  1174. X
  1175. X
  1176. X#define MAGIC    0x1AFB439C
  1177. X
  1178. XHANDLE {
  1179. X    NODE    Node;    /*  link node        */
  1180. X    long    Magic;
  1181. X    LOCK    *Lock;    /*  lock if any     */
  1182. X    long    Handle;    /*  remote handle    */
  1183. X    short   Type;    /*  file type        */
  1184. X    ulong   Prot;    /*  protection bits    */
  1185. X    ulong   Size;    /*  file size        */
  1186. X    STAMP   Date;    /*  date stamp        */
  1187. X    char    *Name;    /*  file name        */
  1188. X};
  1189. X
  1190. END_OF_FILE
  1191. if test 3671 -ne `wc -c <'amiga/doshand/dos.h'`; then
  1192.     echo shar: \"'amiga/doshand/dos.h'\" unpacked with wrong size!
  1193. fi
  1194. # end of 'amiga/doshand/dos.h'
  1195. fi
  1196. if test -f 'amiga/server/scopy.c' -a "${1}" != "-c" ; then 
  1197.   echo shar: Will not clobber existing file \"'amiga/server/scopy.c'\"
  1198. else
  1199. echo shar: Extracting \"'amiga/server/scopy.c'\" \(4424 characters\)
  1200. sed "s/^X//" >'amiga/server/scopy.c' <<'END_OF_FILE'
  1201. X
  1202. X/*
  1203. X *  SCOPY.C    V1.1
  1204. X *
  1205. X *  DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
  1206. X *
  1207. X *  COPY SERVER FOR PUTFILES (DOWNLOADS, i.e. receives files)
  1208. X *
  1209. X *  The current version only accepts one connection at a time.    This server
  1210. X *  handles downloading of data.  This server will eventually be replaced
  1211. X *  by the SGCOPY server.  Currently the SGCOPY server only handles
  1212. X *  uploads.
  1213. X *
  1214. X *  NOTE:   The DNET_WRITE enviroment variable must be 9 or higher or this
  1215. X *        server will refuse connections.
  1216. X *
  1217. X *  Receive:
  1218. X *        'V' NLEN NAME FILELEN       -receive compressed file    (V1.1)
  1219. X *        'W' NLEN NAME FILELEN       -receive file
  1220. X *        'X' NLEN NAME   0           -create and CD into directory
  1221. X *        'Y'  0          0           -restore previous directory
  1222. X *        'C' NLEN NAME   0           -set destination directory
  1223. X *
  1224. X *  length in 68000 longword format.
  1225. X */
  1226. X
  1227. X#include "defs.h"
  1228. X
  1229. Xchar Buf[8192];
  1230. Xchar Buf2[8192];
  1231. X
  1232. Xint putdir ARGS((void *, char *));
  1233. Xint putfile ARGS((void *, char *, int));
  1234. X
  1235. Xint
  1236. Xbrk()
  1237. X{
  1238. X    return(0);
  1239. X}
  1240. X
  1241. Xvoid
  1242. X#ifdef LATTICE
  1243. X_main(str)
  1244. X#else
  1245. X_main(len,str)
  1246. X#endif
  1247. Xchar *str;
  1248. X{
  1249. X    struct MsgPort *port;
  1250. X    PROC    *myproc = (PROC *)FindTask(NULL);
  1251. X    void    *chan;
  1252. X    long    savedir;
  1253. X    long    mask, rmask;
  1254. X
  1255. X    onbreak(brk);
  1256. X
  1257. X    if (strncmp(str, "__dnet", 6) != 0) {
  1258. X    Version("SCopy", VERSION, SCOPY_VERSION);
  1259. X    _exit(0);
  1260. X    }
  1261. X
  1262. X    port = DListen(PORT_FILECOPY);
  1263. X    {
  1264. X    struct Message *msg;
  1265. X    char *dir;
  1266. X
  1267. X    WaitPort(&myproc->pr_MsgPort);
  1268. X    msg = GetMsg(&myproc->pr_MsgPort);
  1269. X    dir = (msg->mn_Node.ln_Name) ? msg->mn_Node.ln_Name : "";
  1270. X    savedir = Lock(dir, SHARED_LOCK);   /* duplicate current dir    */
  1271. X    ReplyMsg(msg);
  1272. X    }
  1273. X    if (!savedir) {
  1274. X    DUnListen(port);
  1275. X    _exit(1);
  1276. X    }
  1277. X    savedir = CurrentDir(savedir);              /* CD dup, returns original */
  1278. X    mask = SIGBREAKF_CTRL_C|(1 << port->mp_SigBit);
  1279. X    for (;;) {
  1280. X    long dupdir = DupLock(myproc->pr_CurrentDir);
  1281. X    rmask = Wait(mask);
  1282. X    if (rmask & SIGBREAKF_CTRL_C) {
  1283. X        UnLock(CurrentDir(dupdir));
  1284. X        break;
  1285. X    }
  1286. X    while (chan = DAccept(port)) {
  1287. X        if (GetEnvVal(DNET_WRITE) >= 9)
  1288. X        putdir(chan, "");
  1289. X        else
  1290. X        DWrite(chan, "S", 1);
  1291. X        DClose(chan);
  1292. X    }
  1293. X    UnLock(CurrentDir(dupdir));
  1294. X    }
  1295. X    UnLock(CurrentDir(savedir));                /* restore original         */
  1296. X    DUnListen(port);
  1297. X}
  1298. X
  1299. Xstatic char Name[128];
  1300. X
  1301. Xint
  1302. Xputdir(chan, dirname)
  1303. Xvoid *chan;
  1304. Xchar *dirname;
  1305. X{
  1306. X    FIB *fib;
  1307. X    long lock;
  1308. X    long oldlock;
  1309. X    long len;
  1310. X    int ret = -1;
  1311. X    unsigned char co, nl, rc;
  1312. X
  1313. X    fib = (FIB *)AllocMem(sizeof(FIB), MEMF_PUBLIC);
  1314. X    if ((lock = Lock(dirname, SHARED_LOCK)) == NULL) {
  1315. X    if (lock = CreateDir(dirname)) {
  1316. X        UnLock(lock);
  1317. X        lock = Lock(dirname, SHARED_LOCK);
  1318. X    }
  1319. X    }
  1320. X    if (lock == NULL || !Examine(lock,fib) || fib->fib_DirEntryType < 0) {
  1321. X    if (lock)
  1322. X        UnLock(lock);
  1323. X    rc = 'N';
  1324. X    DWrite(chan, &rc, 1);
  1325. X    FreeMem(fib, sizeof(FIB));
  1326. X    return(1);
  1327. X    }
  1328. X    rc = 'Y';
  1329. X    DWrite(chan, &rc, 1);
  1330. X    oldlock = CurrentDir(lock);
  1331. X    while (DRead(chan, &co, 1) == 1) {
  1332. X    if (DRead(chan, &nl, 1) != 1 || DRead(chan, Name, nl) != nl)
  1333. X        break;
  1334. X    if (DRead(chan, &len, 4) != 4)
  1335. X        break;
  1336. X    switch(co) {
  1337. X    case 'C':
  1338. X        {
  1339. X        char co = 'N';
  1340. X        long lock = Lock(Name, SHARED_LOCK);    /* CD to dir */
  1341. X        if (!lock) {
  1342. X            if (lock = CreateDir(Name)) {       /* or create */
  1343. X            UnLock(lock);
  1344. X            lock = Lock(Name, SHARED_LOCK);
  1345. X            }
  1346. X        }
  1347. X        if (lock) {
  1348. X            co = 'Y';
  1349. X            UnLock(CurrentDir(lock));
  1350. X        }
  1351. X        DWrite(chan, &co, 1);
  1352. X        }
  1353. X        break;
  1354. X    case 'W':
  1355. X        if (putfile(chan, Name, len) < 0) {
  1356. X        ret = -1;
  1357. X        goto fail;
  1358. X        }
  1359. X        break;
  1360. X    case 'X':
  1361. X        if (putdir(chan, Name) < 0) {
  1362. X        ret = -1;
  1363. X        goto fail;
  1364. X        }
  1365. X        break;
  1366. X    case 'Y':
  1367. X        ret = 1;
  1368. X        co = 'Y';
  1369. X        DWrite(chan, &co, 1);
  1370. X        goto fail;
  1371. X    default:
  1372. X        co = 'N';
  1373. X        DWrite(chan, &co, 1);
  1374. X        break;
  1375. X    }
  1376. X    }
  1377. Xfail:
  1378. X    UnLock(CurrentDir(oldlock));
  1379. X    FreeMem(fib, sizeof(FIB));
  1380. X    return(ret);
  1381. X}
  1382. X
  1383. Xint
  1384. Xputfile(chan, name, len)
  1385. Xvoid *chan;
  1386. Xchar *name;
  1387. Xint len;
  1388. X{
  1389. X    long fh = Open(name, 1006);
  1390. X    long n, r;
  1391. X    char rc;
  1392. X
  1393. X    if (fh == NULL) {
  1394. X    rc = 'N';
  1395. X    DWrite(chan, &rc, 1);
  1396. X    return(0);
  1397. X    }
  1398. X    rc = 'Y';
  1399. X    DWrite(chan, &rc, 1);
  1400. X    while (len) {
  1401. X    r = (len > sizeof(Buf)) ? sizeof(Buf) : len;
  1402. X    n = DRead(chan, Buf, r);
  1403. X    if (n != r)
  1404. X        break;
  1405. X    if (Write(fh, Buf, n) != n)
  1406. X        break;
  1407. X    len -= n;
  1408. X    }
  1409. X    Close(fh);
  1410. X    if (len) {
  1411. X    unlink(name);
  1412. X    return(-1);
  1413. X    }
  1414. X    rc = 'Y';
  1415. X    DWrite(chan, &rc, 1);
  1416. X    return(0);
  1417. X}
  1418. X
  1419. END_OF_FILE
  1420. if test 4424 -ne `wc -c <'amiga/server/scopy.c'`; then
  1421.     echo shar: \"'amiga/server/scopy.c'\" unpacked with wrong size!
  1422. fi
  1423. # end of 'amiga/server/scopy.c'
  1424. fi
  1425. if test -f 'unix/README' -a "${1}" != "-c" ; then 
  1426.   echo shar: Will not clobber existing file \"'unix/README'\"
  1427. else
  1428. echo shar: Extracting \"'unix/README'\" \(5174 characters\)
  1429. sed "s/^X//" >'unix/README' <<'END_OF_FILE'
  1430. X
  1431. X
  1432. X               DNET V2.10 UNIX SIDE
  1433. X
  1434. X               BSD4.2/4.3 compatible
  1435. X
  1436. X    Special note this release: default is to run in 7 bit mode (which
  1437. X    uses a special 6 bit encoding to encode binary data).  The -m0
  1438. X    option has been added for those who can run over full 8 bit nets.
  1439. X
  1440. X    DNET (c)Copyright 1987-1989 Matthew Dillon, All Rights Reserved
  1441. X
  1442. X    Matthew Dillon
  1443. X    891 Regal Rd
  1444. X    Berkeley, Ca. 94708
  1445. X    USA
  1446. X
  1447. X    ...!ihnp4!ucbvax!dillon     USENET
  1448. X    dillon@ucbvax.Berkeley.edu    ARPANET
  1449. X    ucbvax.berkeley.edu pub/amiga    ARPANET-FTP
  1450. X
  1451. X                UNIX SETUP
  1452. X
  1453. X    The directory structure must remain intact.  simply say MAKE
  1454. X    in the main directory and it ought to compile.    There might be
  1455. X    minor problems depending on how compatible your UNIX is with
  1456. X    BSD4.3 UNIX ..    I have successfully compiled DNet on the following
  1457. X    machines:
  1458. X
  1459. X            Dec Vax 7xx
  1460. X            Sun 3
  1461. X            Sequent
  1462. X
  1463. X    (1) Create a directory.  For example, ~/.DNET   WARNING!  This
  1464. X        directory must be on a local partition.  DNET uses a unix
  1465. X        domain socket and these do not work over network fileservers.
  1466. X
  1467. X    (2) Modify your .cshrc to add the following line:
  1468. X
  1469. X        setenv DNETDIR  ~/.DNET/
  1470. X
  1471. X        (or wherever you put it.  NOTE! You MUST HAVE THE TRAILING
  1472. X         SLASH!)
  1473. X
  1474. X    (3) All binaries are usually kept in dnet.unix/bin, add this
  1475. X        directory to your path (in your .cshrc) so DNet can find
  1476. X        the clients.
  1477. X
  1478. X    (4) Place the file 'dnet.servers' in $DNETDIR.  Modify the file
  1479. X        according to your home directory and where you have put the
  1480. X        servers (usually in dnet.unix/bin).  USE ABSOLUTE PATHS,
  1481. X        DNET.SERVERS DOES NOT UNDERSTAND ~.
  1482. X
  1483. X    NOTE: You may want to chmod $DNETDIR 700 to disallow any
  1484. X    unauthorized access to the network.
  1485. X
  1486. X
  1487. X                 DIALING UP FROM AN AMIGA
  1488. X
  1489. X    Follow the installation instructions for the Amiga side.  When
  1490. X    you dial up the UNIX system you will eventually get a prompt.
  1491. X    NOTE!  DNET normally uses 7 bit - even parity for dialing up,
  1492. X    then switches to 8 bit no parity for the protocol.  Sometimes
  1493. X    the modem or port selector will switch into 7 bit + parity mode
  1494. X    and NOT SWITCH OUT.  For this reason, you might want to use the
  1495. X    -8 option for the Amiga side of DNET (read the docs in the Amiga
  1496. X    section).
  1497. X
  1498. X    You may have to force parity before running DNet.  To force parity
  1499. X    to even use (and do this only if running the -Z2 option from the
  1500. X    Amiga side dnet):          THIS IS NOT NORMALLY DONE.
  1501. X
  1502. X    % stty -odd
  1503. X
  1504. X    From the DNET window's CSH prompt, start the protocol with:
  1505. X
  1506. X    % dnet
  1507. X
  1508. X    That was easy.    The DNet window should go away and an FTERM window
  1509. X    should open.  This does not mean success!  If the FTERM window
  1510. X    closes again with the message "unable to connect", it was unable
  1511. X    to connect.  There are several possibilities:
  1512. X
  1513. X    (a) You do not have an 8 bit connection from your amiga to the
  1514. X        UNIX host (DNet must be able to send and receive all 256
  1515. X        character codes).
  1516. X
  1517. X    (b) You did not setup the DNETDIR enviroment variable properly
  1518. X
  1519. X    (c) You did not copy dnet.servers into $DNETIDR
  1520. X
  1521. X    (d) The absolute file path in dnet.servers for server #8192 (that
  1522. X        FTerm tires to connect to) is not correct.
  1523. X
  1524. X                    KILLING DNET
  1525. X
  1526. X    In most cases simply turning off the modem will suffice.  You can
  1527. X    kill dnet more cleanly with the following sequence:
  1528. X
  1529. X    (1) From an Amiga CLI, run the QuitDnet command.  This will kill
  1530. X        the packet protocol and cause the remote DNet to exit.  It
  1531. X        will then break the local DNet.
  1532. X
  1533. X        You should get the original (small) DNet window and the
  1534. X        original login shell. If you get the DNet window but not the
  1535. X        shell (you can't type), the protocol may still be running on
  1536. X        the other end, in which case it didn't work for some unknown
  1537. X        reason.  Restart the protocol w/ the appropriate menu option
  1538. X        and try 'quitdnet' again.
  1539. X
  1540. X    (3) logout normally and close the DNet window.  Turn off your
  1541. X        modem.
  1542. X
  1543. X        If the kill sequence in (2) does not work, you can simply
  1544. X        hangup the line.
  1545. X
  1546. X                 HANGING SERVER PROCESSES
  1547. X
  1548. X    The UNIX side servers are normally left running when the protocol
  1549. X    dies.  These are very very very small and take 0 CPU (they are
  1550. X    simply waiting for connections).  These servers will still be
  1551. X    there when you log in again and DNet will use them.
  1552. X
  1553. X    You can kill UNIX side servers at any time.
  1554. X
  1555. X    Many of the same clients and servers exist on the UNIX end as
  1556. X    on the Amiga end.  The UNIX end is missing several.  The UNIX
  1557. X    end implements two commands called dsoc and draw which can be
  1558. X    used to connect to (in cooked or raw tty mode) specific servers
  1559. X    (by port #) on the Amiga side.  For example, to connect to the
  1560. X    printer server on the amiga side:
  1561. X
  1562. X    % dsoc 8198
  1563. X    This is a test
  1564. X    ^D
  1565. X    %
  1566. X
  1567. X    Dumps to PRT: on the Amiga "This is a test"  Gee Wiz!
  1568. X
  1569. X                SECURITY W/ UNIX
  1570. X
  1571. X    DNet will be as secure as your account, assuming you chmod DNETDIR
  1572. X    700 (so nobody else has access to the unix domain sockets).  From
  1573. X    Home (on the Amiga), I usually RUN DNET -X , login, start the
  1574. X    protocol, and leave it running all day.
  1575. X
  1576. X    The -X option turns of security (sets all security levels to 9),
  1577. X    thus allowing me to drive to the university and at any time from
  1578. X    my UNIX account do a getfiles or putfiles from and to my Amiga.
  1579. X
  1580. X    Refer to the amiga side documentation for more information.
  1581. X
  1582. X
  1583. X
  1584. END_OF_FILE
  1585. if test 5174 -ne `wc -c <'unix/README'`; then
  1586.     echo shar: \"'unix/README'\" unpacked with wrong size!
  1587. fi
  1588. # end of 'unix/README'
  1589. fi
  1590. if test -f 'unix/client/putfiles.c' -a "${1}" != "-c" ; then 
  1591.   echo shar: Will not clobber existing file \"'unix/client/putfiles.c'\"
  1592. else
  1593. echo shar: Extracting \"'unix/client/putfiles.c'\" \(3756 characters\)
  1594. sed "s/^X//" >'unix/client/putfiles.c' <<'END_OF_FILE'
  1595. X
  1596. X/*
  1597. X *  PUTFILES.C
  1598. X *
  1599. X *    DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved
  1600. X *
  1601. X *  Download one or more files from the remote computer
  1602. X *
  1603. X *  PUTFILES file/dir1 file/dir2 ... file/dirN
  1604. X *
  1605. X *  placed in directory server ran from on remote host.
  1606. X */
  1607. X
  1608. X#include <sys/types.h>
  1609. X#include <sys/stat.h>
  1610. X#include <sys/dir.h>
  1611. X#include <stdio.h>
  1612. X#include <sys/file.h>
  1613. X#include "../server/servers.h"
  1614. X
  1615. Xchar Buf[1024];
  1616. X
  1617. Xtypedef struct stat STAT;
  1618. X
  1619. Xmain(ac,av)
  1620. Xchar *av[];
  1621. X{
  1622. X    long chan;
  1623. X    long n, len, orig;
  1624. X    long fh;
  1625. X    short i, j;
  1626. X    char fn;
  1627. X
  1628. X    if (ac == 1) {
  1629. X    puts("putfiles V1.00 (c)Copyright 1987, Matthew Dillon, All Rights Reserved");
  1630. X    puts("putfiles file/dir file/dir .....");
  1631. X    exit(1);
  1632. X    }
  1633. X
  1634. X    chan = DOpen(NULL, PORT_FILECOPY, -80, 126);
  1635. X    if (chan < 0) {
  1636. X    puts("Unable to connect");
  1637. X    exit(1);
  1638. X    }
  1639. X    ggread(chan, &fn, 1);
  1640. X    if (fn != 'Y') {
  1641. X    puts("Remote Server Software Error");
  1642. X    close(chan);
  1643. X    }
  1644. X    for (i = 1; i < ac; ++i) {
  1645. X    if (strncmp(av[i], "-d", 2) == 0) {/*-ddir or -d dir*/
  1646. X        char *dir = av[i]+2;
  1647. X        if (*dir == 0 && i+1 < ac) {
  1648. X        ++i;
  1649. X        dir = av[i];
  1650. X        }
  1651. X        if (writehdr_nc(chan, 'C', dir, 0) != 'Y') {
  1652. X        puts ("unable to go to specified remote directory");
  1653. X        break;
  1654. X        }
  1655. X    } else {
  1656. X        if (putname(chan, av[i]) < 0)
  1657. X            break;
  1658. X    }
  1659. X    }
  1660. X    printf("\nclosing... ");
  1661. X    fflush(stdout);
  1662. X    close(chan);
  1663. X    puts("done");
  1664. X}
  1665. X
  1666. Xputname(chan, file)
  1667. Xchar *file;
  1668. X{
  1669. X    STAT sstat;
  1670. X    char svdir[256];
  1671. X    int ret;
  1672. X
  1673. X    printf("%-20s ", file);
  1674. X    if (stat(file, &sstat) < 0) {
  1675. X    puts("NOT FOUND");
  1676. X    return(1);
  1677. X    }
  1678. X    if (sstat.st_mode & S_IFDIR) {
  1679. X    DIR *dir;
  1680. X    struct direct *de;
  1681. X
  1682. X    getwd(svdir);
  1683. X    puts("DIR");
  1684. X    chdir(file);
  1685. X    if (writehdr(chan, 'X', file, 0) != 'Y') {
  1686. X        puts("Remote unable to make directory");
  1687. X        goto f1;
  1688. X    }
  1689. X    if (dir = opendir(".")) {
  1690. X        while (de = readdir(dir))  {
  1691. X        if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name,"..")==0)
  1692. X            continue;
  1693. X        if (putname(chan, de->d_name) < 0) {
  1694. X            ret = -1;
  1695. X            break;
  1696. X        }
  1697. X        }
  1698. X    }
  1699. X    writehdr(chan, 'Y', "?", 0);
  1700. Xf1:
  1701. X    chdir(svdir);
  1702. X    } else {
  1703. X    ret = putfile(chan, file);
  1704. X    }
  1705. X    return(ret);
  1706. X}
  1707. X
  1708. Xputfile(chan, file)
  1709. Xchar *file;
  1710. X{
  1711. X    int fd = open(file, O_RDONLY);
  1712. X    long n, r, len;
  1713. X    long ttl = 0;
  1714. X    char co;
  1715. X
  1716. X    fflush(stdout);
  1717. X    if (fd < 0) {
  1718. X    puts("FILE NOT FOUND");
  1719. X    return(0);
  1720. X    }
  1721. X    len = ttl = lseek(fd, 0, 2);
  1722. X    lseek(fd, 0, 0);
  1723. X    if (writehdr(chan, 'W', file, len) != 'Y') {
  1724. X    puts("REMOTE UNABLE TO ACCEPT FILE");
  1725. X    close(fd);
  1726. X    return(0);
  1727. X    }
  1728. X    printf("%6ld/%-6ld", ttl - len, ttl);
  1729. X    while (len) {
  1730. X    fflush(stdout);
  1731. X    r = (len > sizeof(Buf)) ? sizeof(Buf) : len;
  1732. X    n = read(fd, Buf, r);
  1733. X    if (n != r) {
  1734. X        puts("Local File error");
  1735. X        close(fd);
  1736. X        return(-1);
  1737. X    }
  1738. X    if (gwrite(chan, Buf, n) != n) {
  1739. X        puts("Remote error");
  1740. X        close(fd);
  1741. X        return(-1);
  1742. X    }
  1743. X    len -= n;
  1744. X    printf("\010\010\010\010\010\010\010\010\010\010\010\010\010");
  1745. X    printf("%6ld/%-6ld", ttl - len, ttl);
  1746. X    }
  1747. X    close(fd);
  1748. X    if (len) {
  1749. X    puts("REMOTE ERROR");
  1750. X    return(-1);
  1751. X    }
  1752. X    printf("  Queued, waiting... ");
  1753. X    fflush(stdout);
  1754. X    ggread(chan, &co, 1);
  1755. X    if (co != 'Y') {
  1756. X    puts("Remote Server Software Error");
  1757. X    return(-1);
  1758. X    }
  1759. X    puts("OK");
  1760. X    return(0);
  1761. X}
  1762. X
  1763. Xwritehdr(chan, c, name, len)
  1764. Xunsigned char c;
  1765. Xchar *name;
  1766. Xlong len;
  1767. X{
  1768. X    short i;
  1769. X    for (i = strlen(name) - 1; i >= 0; --i) {
  1770. X    if (name[i] == '/' || name[i] == ':')
  1771. X        break;
  1772. X    }
  1773. X    name += i + 1;
  1774. X    return(writehdr_nc(chan, c, name, len));
  1775. X}
  1776. X
  1777. Xwritehdr_nc(chan, c, name, len)
  1778. Xunsigned char c;
  1779. Xchar *name;
  1780. Xlong len;
  1781. X{
  1782. X    gwrite(chan, &c, 1);
  1783. X    c = strlen(name) + 1;
  1784. X    gwrite(chan, &c, 1);
  1785. X    gwrite(chan, name, c);
  1786. X    len = htonl68(len);
  1787. X    gwrite(chan, &len, 4);
  1788. X    if (ggread(chan, &c, 1) == 1)
  1789. X    return(c);
  1790. X    return(-1);
  1791. X}
  1792. X
  1793. END_OF_FILE
  1794. if test 3756 -ne `wc -c <'unix/client/putfiles.c'`; then
  1795.     echo shar: \"'unix/client/putfiles.c'\" unpacked with wrong size!
  1796. fi
  1797. # end of 'unix/client/putfiles.c'
  1798. fi
  1799. if test -f 'unix/dnet/internal.c' -a "${1}" != "-c" ; then 
  1800.   echo shar: Will not clobber existing file \"'unix/dnet/internal.c'\"
  1801. else
  1802. echo shar: Extracting \"'unix/dnet/internal.c'\" \(4223 characters\)
  1803. sed "s/^X//" >'unix/dnet/internal.c' <<'END_OF_FILE'
  1804. X
  1805. X/*
  1806. X *  INTERNAL.C
  1807. X *
  1808. X *    DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved
  1809. X *
  1810. X *    Usually SCMD_OPEN requests attempt to connect() to the UNIX
  1811. X *    domain socket of the server.  However, some 'ports' are designated
  1812. X *    as internal to DNET.  They reside here.
  1813. X *
  1814. X *    -IALPHATERM
  1815. X */
  1816. X
  1817. X#include "dnet.h"
  1818. X#include "../server/servers.h"
  1819. X#include <sys/stat.h>
  1820. X#include <sys/wait.h>
  1821. X#include <sys/resource.h>
  1822. X#include <sys/uio.h>
  1823. X#include <strings.h>
  1824. X
  1825. Xextern char *getenv();
  1826. X
  1827. Xisinternalport(port)
  1828. Xuword port;
  1829. X{
  1830. X    if (port == PORT_IALPHATERM)
  1831. X    return(1);
  1832. X    return(0);
  1833. X}
  1834. X
  1835. Xiconnect(ps, port)
  1836. Xint *ps;
  1837. Xuword port;
  1838. X{
  1839. X    if (port == PORT_IALPHATERM)
  1840. X    return(ialphaterm_connect(ps, port));
  1841. X    return(-1);
  1842. X}
  1843. X
  1844. Xialphaterm_connect(pmaster)
  1845. Xint *pmaster;
  1846. X{
  1847. X    struct sgttyb sg;
  1848. X    struct tchars tc;
  1849. X    struct ltchars ltc;
  1850. X#ifdef TIOCGSIZE
  1851. X    struct ttysize ts;
  1852. X#else
  1853. X#ifdef TIOCGWINSZ
  1854. X    struct winsize ws;
  1855. X#endif
  1856. X#endif
  1857. X    int lmode;
  1858. X    int fdmaster;
  1859. X    int fdslave;
  1860. X    int pid;
  1861. X    char *slavename;
  1862. X
  1863. X    ioctl(0, TIOCGETP, (char *)&sg);
  1864. X    ioctl(0, TIOCGETC, (char *)&tc);
  1865. X    ioctl(0, TIOCGLTC, (char *)<c);
  1866. X    ioctl(0, TIOCLGET, (char *)&lmode);
  1867. X#ifdef TIOCGSIZE
  1868. X    ioctl(0, TIOCGSIZE, &ts);
  1869. X#else
  1870. X#ifdef TIOCGWINSZ
  1871. X    ioctl(0, TIOCGWINSZ, &ws);
  1872. X#endif
  1873. X#endif
  1874. X
  1875. X    sg.sg_flags &= ~(RAW);
  1876. X    sg.sg_flags |= ECHO;
  1877. X#ifdef TIOCGSIZE
  1878. X    ts.ts_lines = 23;
  1879. X    ts.ts_cols = 77;
  1880. X#else
  1881. X#ifdef TIOCGWINSZ
  1882. X    ws.ws_row = 23;
  1883. X    ws.ws_col = 77;
  1884. X#endif
  1885. X#endif
  1886. X
  1887. X    if (DDebug)
  1888. X    fprintf(stderr, "PTY openning internal pty\n");
  1889. X    if (openpty(&fdmaster, &fdslave, &slavename) >= 0) {
  1890. X    if (DDebug)
  1891. X        fprintf(stderr, "PTY open successfull\n");
  1892. X    if ((pid = fork()) == NULL) {
  1893. X        int i;
  1894. X        setenv("DNET=", "IALPHATERM");
  1895. X        setuid(getuid());
  1896. X        signal(SIGHUP, SIG_DFL);
  1897. X        signal(SIGINT, SIG_DFL);
  1898. X        signal(SIGQUIT, SIG_DFL);
  1899. X        signal(SIGTERM, SIG_DFL);
  1900. X        signal(SIGCHLD, SIG_DFL);
  1901. X        signal(SIGTSTP, SIG_IGN);
  1902. X        ioctl(open("/dev/tty", 2), TIOCNOTTY, NULL);
  1903. X        close(open(slavename, 0));
  1904. X        dup2(fdslave, 0);
  1905. X        dup2(0, 1);
  1906. X        dup2(0, 2);
  1907. X        for (i = 3; i < 256; ++i)
  1908. X        close(i);
  1909. X        ioctl(0, TIOCSETN, &sg);
  1910. X        ioctl(0, TIOCSETC, &tc);
  1911. X        ioctl(0, TIOCSLTC, <c);
  1912. X        ioctl(0, TIOCLSET, &lmode);
  1913. X#ifdef TIOCSSIZE
  1914. X            ioctl(0, TIOCSSIZE, &ts);
  1915. X#else
  1916. X#ifdef TIOCSWINSZ
  1917. X            ioctl(0, TIOCSWINSZ, &ws);
  1918. X#endif
  1919. X#endif
  1920. X        {
  1921. X        char *shell = getenv("SHELL");
  1922. X        char *home = getenv("HOME");
  1923. X        if (!shell)
  1924. X            shell = "/bin/sh";
  1925. X        if (!home)
  1926. X            home = ".";
  1927. X        chdir(home);
  1928. X        execl(shell, "-fshell", NULL);
  1929. X        perror(shell);
  1930. X        }
  1931. X        _exit(1);
  1932. X    }
  1933. X    if (pid > 0) {
  1934. X        *pmaster = fdmaster;
  1935. X        close(fdslave);
  1936. X        if (DDebug)
  1937. X                fprintf(stderr, "PTY OPEN OK.2\n");
  1938. X        return(1);
  1939. X    }
  1940. X    close(fdmaster);
  1941. X    close(fdslave);
  1942. X    if (DDebug)
  1943. X            fprintf(stderr, "PTY OPEN FAILURE.1\n");
  1944. X    }
  1945. X    if (DDebug)
  1946. X        fprintf(stderr, "PTY OPEN FAILURE.2\n");
  1947. X    return(-1);
  1948. X}
  1949. X
  1950. Xopenpty(pfdm, pfds, pnames)
  1951. Xint *pfdm;
  1952. Xint *pfds;
  1953. Xchar **pnames;
  1954. X{
  1955. X    static char ptcs[] = { "0123456789abcdef" };
  1956. X    static char plate[] = { "/dev/ptyxx" };
  1957. X    struct stat stat;
  1958. X    int i;
  1959. X    int j;
  1960. X
  1961. X    for (i = 'p';; ++i) {
  1962. X    plate[8] = i;
  1963. X    plate[9] = ptcs[0];
  1964. X    if (lstat(plate, &stat) < 0)
  1965. X        break;
  1966. X    for (j = 0; ptcs[j]; ++j) {
  1967. X        plate[9] = ptcs[j];
  1968. X        plate[5] = 'p';
  1969. X        if ((*pfdm = open(plate, O_RDWR)) >= 0) {
  1970. X        plate[5] = 't';
  1971. X        if ((*pfds = open(plate, O_RDWR)) >= 0) {
  1972. X            *pnames = plate;
  1973. X            if (DDebug)
  1974. X            fprintf(stderr, "PTY FOUND %s\n", *pnames);
  1975. X            return(1);
  1976. X        }
  1977. X        close(*pfdm);
  1978. X        }
  1979. X    }
  1980. X    }
  1981. X    return(-1);
  1982. X}
  1983. X
  1984. Xisetrows(fd, rows)
  1985. X{
  1986. X#ifdef TIOCSSIZE
  1987. X    struct ttysize ts;
  1988. X    if (ioctl(fd, TIOCGSIZE, &ts) >= 0) {
  1989. X    ts.ts_lines = rows;
  1990. X    ioctl(fd, TIOCSSIZE, &ts);
  1991. X    }
  1992. X#else
  1993. X#ifdef TIOCSWINSZ
  1994. X    struct winsize ws;
  1995. X    if (ioctl(fd, TIOCGWINSZ, &ws) >= 0) {
  1996. X    ws.ws_row = rows;
  1997. X    ioctl(fd, TIOCSWINSZ, &ws);
  1998. X    }
  1999. X#endif
  2000. X#endif
  2001. X}
  2002. X
  2003. Xisetcols(fd, cols)
  2004. X{
  2005. X#ifdef TIOCSSIZE
  2006. X    struct ttysize ts;
  2007. X    if (ioctl(fd, TIOCGSIZE, &ts) >= 0) {
  2008. X    ts.ts_cols = cols;
  2009. X    ioctl(fd, TIOCSSIZE, &ts);
  2010. X    }
  2011. X#else
  2012. X#ifdef TIOCSWINSZ
  2013. X    struct winsize ws;
  2014. X    if (ioctl(fd, TIOCGWINSZ, &ws) >= 0) {
  2015. X    ws.ws_col = cols;
  2016. X    ioctl(fd, TIOCSWINSZ, &ws);
  2017. X    }
  2018. X#endif
  2019. X#endif
  2020. X}
  2021. X
  2022. END_OF_FILE
  2023. if test 4223 -ne `wc -c <'unix/dnet/internal.c'`; then
  2024.     echo shar: \"'unix/dnet/internal.c'\" unpacked with wrong size!
  2025. fi
  2026. # end of 'unix/dnet/internal.c'
  2027. fi
  2028. if test -f 'unix/doc/dnetlib.doc' -a "${1}" != "-c" ; then 
  2029.   echo shar: Will not clobber existing file \"'unix/doc/dnetlib.doc'\"
  2030. else
  2031. echo shar: Extracting \"'unix/doc/dnetlib.doc'\" \(3568 characters\)
  2032. sed "s/^X//" >'unix/doc/dnetlib.doc' <<'END_OF_FILE'
  2033. X
  2034. XUNIX/DNETLIB
  2035. X
  2036. X    UNIX END DNET LIBRARY INTERFACE
  2037. X
  2038. X    See the server source for good examples of usage.
  2039. X
  2040. Xlong    private;
  2041. Xuword    port
  2042. Xchar     *buf;
  2043. Xint     fd;
  2044. Xint    res1..5, bytes
  2045. Xchar    pri;
  2046. Xlong    val68, valvax;
  2047. X
  2048. Xprivate    = DListen(port)                listen on a port (server)
  2049. X     fd = DAccept(private)            accept a connection (server)
  2050. X      DNAAccept(private)            don't accept a conn.(server)
  2051. X     fd = DOpen(host, port, txpri, rxpri)    open a remote connection (client)
  2052. X   res1 = read(fd, buf, bytes)            standard unix read()
  2053. X   res2 = gread(fd, buf, bytes)            (see below)
  2054. X   res3 = ggread(fd, buf, bytes)        (see below)
  2055. X   res4 = write(fd, buf, bytes)            standard unix write()
  2056. X   res5 = gwrite(fd, buf, bytes)        (see below)
  2057. X      close(fd);
  2058. X
  2059. X   val68 = ntohl68(valvax)    convert to and from MC68000 longword format.
  2060. X   valvax= htonl68(val68)
  2061. X
  2062. X
  2063. XDListen()    sets up a UNIX domain socket in the current directory unless
  2064. X        another is specified by the DNETDIR enviroment variable.
  2065. X        Returns a private structure pointer or NULL on error.
  2066. X
  2067. X        This call will override any existing server for the port in
  2068. X        the directory permanently.  It does not cause an existing
  2069. X        server to exit, however, and you should be careful to kill
  2070. X        old servers before starting new ones.  See the source for a
  2071. X        template of correct server code.
  2072. X
  2073. XDAccept()    Accepts a new connection on the port.  Returns a file 
  2074. X        descriptor or a negative value.  This call will block.
  2075. X
  2076. XDOpen()        Attempt to connect to a port on the remote machine.  Returns
  2077. X        a file descriptor or a negative value.  The error is either
  2078. X        due to not finding DNET's master port (DNET must be running),
  2079. X        or the remote server not running.
  2080. X
  2081. X        This call looks in the current directory for the master
  2082. X        socket unless another is specified by the DNETDIR enviroment 
  2083. X        variable.
  2084. X
  2085. X        Two priorities are specified.  One for sending, and one for
  2086. X        receiving data.  A priority is a value -127 to 126 inclusive,
  2087. X        with 126 the highest priority.  Normally, priorities range
  2088. X        from -80 (file transfers) to +20 (terminal window).
  2089. X
  2090. XDEof()        Send an EOF without closing the connection.  Currently doesn't
  2091. X        work worth shit, so don't use it.
  2092. X
  2093. Xwrite()        Standard UNIX write call.  But we are dealing with a socket
  2094. X        here, so one must be careful of the return value.  (1) WRITE()
  2095. X        may not return the # bytes requested to write, but less,
  2096. X        (2) WRITE() may return a negative value indicating an error or
  2097. X        that it was interrupted or that it would have blocked (if you
  2098. X        have got non-blocking IO setup).  (3) WRITE() returns 0 on 
  2099. X        socket EOF.
  2100. X
  2101. Xgwrite()    This call will write all the bytes specified, whether the
  2102. X        socket is non-blocking or not.  It handles restarting the
  2103. X        WRITE() call on EINTR and properly handles EWOULDBLOCK.
  2104. X
  2105. X        It returns the number bytes requested or fewer on error.  If
  2106. X        fewer bytes are returned you should close the socket and exit.
  2107. X
  2108. Xread()        Standard UNIX read call.  But we are still dealing with a 
  2109. X        socket here and anything might happen.  READ() can return fewer
  2110. X        than the number of bytes requested, 0 on EOF, or a negative
  2111. X        number indicating various errors.
  2112. X
  2113. Xgread()        GREAD() handles retrying if the EINTR error occurs.  GREAD()
  2114. X        blocks until at least one character is received (or EOF), and
  2115. X        does this even if the socket is marked non-blocking.  GREAD()
  2116. X        returns 0 on EOF/ERROR.
  2117. X
  2118. Xggread()    GGREAD() not only retries on EINTR, but will block until ALL
  2119. X        the requested bytes are read in, even if the socket is marked
  2120. X        non-blocking.  GGREAD() returns -1 on EOF/ERROR.  You can also
  2121. X        tell if an EOF/ERROR occured if fewer than the requested 
  2122. X        number of bytes are read.
  2123. X
  2124. END_OF_FILE
  2125. if test 3568 -ne `wc -c <'unix/doc/dnetlib.doc'`; then
  2126.     echo shar: \"'unix/doc/dnetlib.doc'\" unpacked with wrong size!
  2127. fi
  2128. # end of 'unix/doc/dnetlib.doc'
  2129. fi
  2130. if test -f 'unix/server/sgcopy.c' -a "${1}" != "-c" ; then 
  2131.   echo shar: Will not clobber existing file \"'unix/server/sgcopy.c'\"
  2132. else
  2133. echo shar: Extracting \"'unix/server/sgcopy.c'\" \(5462 characters\)
  2134. sed "s/^X//" >'unix/server/sgcopy.c' <<'END_OF_FILE'
  2135. X
  2136. X/*
  2137. X *  SGCOPY.C     V1.1
  2138. X *
  2139. X *  DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
  2140. X *
  2141. X *  GET-COPY SERVER    (NEW COPY SERVER)
  2142. X *
  2143. X *  The current version only accepts one connection at a time.    This server
  2144. X *  will send requested files to the remote machine.
  2145. X *
  2146. X *  length in 68000 longword format.
  2147. X */
  2148. X
  2149. X#include <sys/types.h>
  2150. X#include <sys/stat.h>
  2151. X#include <sys/wait.h>
  2152. X#include <sys/time.h>
  2153. X#include <sys/dir.h>
  2154. X#include <sys/file.h>
  2155. X#include <sys/resource.h>
  2156. X#include <stdio.h>
  2157. X#include <errno.h>
  2158. X#include <signal.h>
  2159. X
  2160. X#include "servers.h"
  2161. X
  2162. Xtypedef struct {
  2163. X    char    Cmd;
  2164. X    char    Str[64];
  2165. X    long    Val;
  2166. X} HDR;
  2167. X
  2168. Xtypedef unsigned char ubyte;
  2169. Xchar *getnamepart();
  2170. Xchar *getdirpart();
  2171. X
  2172. Xchar Buf[4096];
  2173. Xint Chan;
  2174. X
  2175. Xchandler()
  2176. X{
  2177. X    union wait stat;
  2178. X    struct rusage rus;
  2179. X    while (wait3(&stat, WNOHANG, &rus) > 0);
  2180. X}
  2181. X
  2182. Xmain(ac,av)
  2183. Xchar *av[];
  2184. X{
  2185. X    long chann = DListen(PORT_GFILECOPY);
  2186. X    int fd;
  2187. X    int n;
  2188. X    char buf[256];
  2189. X    extern int errno;
  2190. X
  2191. X    if (av[1])
  2192. X    chdir(av[1]);
  2193. X    signal(SIGCHLD, chandler);
  2194. X    signal(SIGPIPE, SIG_IGN);
  2195. X    for (;;) {
  2196. X    fd = DAccept(chann);
  2197. X    if (fd < 0) {
  2198. X        if (errno == EINTR)
  2199. X        continue;
  2200. X        break;
  2201. X    }
  2202. X    if (fork() == NULL) {
  2203. X        SGCopy(fd);
  2204. X        _exit(1);
  2205. X    }
  2206. X    close(fd);
  2207. X    }
  2208. X    perror("SCOPY");
  2209. X}
  2210. X
  2211. XSGCopy(fd)
  2212. Xint fd;
  2213. X{
  2214. X    short error = 0;
  2215. X    static HDR Hdr;
  2216. X
  2217. X    Chan = fd;
  2218. X    error = WriteHeader('H', "Hello, GCopy server V1.30", 0);
  2219. X    if (error)
  2220. X    return(error);
  2221. X    switch(ReadHeader(&Hdr)) {
  2222. X    default:
  2223. X    case -1:
  2224. X    error = 1;
  2225. X    return(error);
  2226. X    case 'H':
  2227. X    break;
  2228. X    }
  2229. X    while (!error) {
  2230. X    switch(ReadHeader(&Hdr)) {
  2231. X    case 'G':
  2232. X        {
  2233. X        char svdir[1024];
  2234. X        getwd(svdir);
  2235. X        if (chdir(getdirpart(Hdr.Str)) < 0) {
  2236. X            error = WriteHeader('N', "Unable to cd to dir", 0);
  2237. X        } else {
  2238. X                error = PutObject(getnamepart(Hdr.Str));
  2239. X        }
  2240. X        chdir(svdir);
  2241. X        }
  2242. X        break;
  2243. X    case 'E':
  2244. X        goto done;
  2245. X    case 'P':   /*  put-files, not implemented  */
  2246. X    default:
  2247. X        error = 1;
  2248. X        break;
  2249. X    }
  2250. X    }
  2251. Xdone:
  2252. X    ;
  2253. X}
  2254. X
  2255. XPutObject(str)
  2256. Xchar *str;
  2257. X{
  2258. X    struct stat stat;
  2259. X    short error = 0;
  2260. X
  2261. X    if (lstat(str, &stat) < 0) {
  2262. X    error = WriteHeader('N', "Unable to find object", 0);
  2263. X    return(0);
  2264. X    }
  2265. X    if (stat.st_mode & S_IFDIR) {
  2266. X    error = PutDir(str);
  2267. X    } else {
  2268. X    error = PutFile(str);
  2269. X    }
  2270. X    return(0);
  2271. X}
  2272. X
  2273. XPutDir(name)
  2274. Xchar *name;
  2275. X{
  2276. X    struct stat stat;
  2277. X    char svdir[1024];
  2278. X    static HDR Hdr;
  2279. X    short error = 0;
  2280. X    char *fn = getnamepart(name);
  2281. X    DIR *dir;
  2282. X    struct direct *de;
  2283. X
  2284. X    if (lstat(name, &stat) < 0 || !(dir = opendir(name))) {
  2285. X    WriteHeader('N', "Possible Disk Error", 0);
  2286. X    error = 1;
  2287. X    goto done;
  2288. X    }
  2289. X    if (error = WriteHeader('D', fn, 0)) 
  2290. X    goto done;
  2291. X    switch(ReadHeader(&Hdr)) {
  2292. X    case 'Y':
  2293. X    break;
  2294. X    case 'S':
  2295. X    goto done;
  2296. X    case 'N':
  2297. X    error = 1;
  2298. X    break;
  2299. X    default:
  2300. X    error = 1;
  2301. X    break;
  2302. X    }
  2303. X    if (error)
  2304. X    goto done;
  2305. X
  2306. X    getwd(svdir);
  2307. X    if (chdir(name) < 0) {
  2308. X    error = 1;
  2309. X    WriteHeader('N', "unable to chdir", 0);
  2310. X    }
  2311. X    if (error)
  2312. X    goto done;
  2313. X
  2314. X    while (de = readdir(dir)) {
  2315. X    if (strcmp(de->d_name, ".") == 0)
  2316. X        continue;
  2317. X    if (strcmp(de->d_name, "..") == 0)
  2318. X        continue;
  2319. X    if (lstat(de->d_name, &stat) < 0) {
  2320. X        continue;
  2321. X    }
  2322. X    if (stat.st_mode & S_IFDIR) {
  2323. X        error = PutDir(de->d_name);
  2324. X    } else {
  2325. X        error = PutFile(de->d_name);
  2326. X    }
  2327. X    if (error)
  2328. X        break;
  2329. X    }
  2330. X    WriteHeader('E', NULL, 0);
  2331. X    chdir(svdir);
  2332. Xdone:
  2333. X    return(error);
  2334. X}
  2335. X
  2336. XPutFile(name)
  2337. Xchar *name;
  2338. X{
  2339. X    int fd = -1;
  2340. X    static HDR Hdr;
  2341. X    long len;
  2342. X    short error = 0;
  2343. X    char *fn = getnamepart(name);
  2344. X
  2345. X    fd = open(fn, O_RDONLY, 0);
  2346. X    if (fd < 0) {       /*  don't do anything if unable to open it */
  2347. X    WriteHeader('N', "file not readable", 0);
  2348. X    goto done;
  2349. X    }
  2350. X    len = lseek(fd, 0L, 2);
  2351. X    if (error = WriteHeader('F', fn, len))
  2352. X    goto done;
  2353. X    switch(ReadHeader(&Hdr)) {
  2354. X    case 'Y':
  2355. X    lseek(fd, Hdr.Val, 0);  /*  start pos.  */
  2356. X    len -= Hdr.Val;
  2357. X    if (len < 0)
  2358. X        len = 0;
  2359. X    break;
  2360. X    case 'S':
  2361. X    goto done;
  2362. X    case 'N':
  2363. X    error = 1;
  2364. X    break;
  2365. X    default:
  2366. X    error = 1;
  2367. X    break;
  2368. X    }
  2369. X    if (error)
  2370. X    goto done;
  2371. X    while (len) {
  2372. X    register long n = (len > sizeof(Buf)) ? sizeof(Buf) : len;
  2373. X
  2374. X    if (read(fd, Buf, n) != n) {    /*  read failed! */
  2375. X        error = 10;
  2376. X        goto done;
  2377. X    }
  2378. X    if (gwrite(Chan, Buf, n) != n) {
  2379. X        error = 10;
  2380. X        goto done;
  2381. X    }
  2382. X    len -= n;
  2383. X    }
  2384. Xdone:
  2385. X    if (fd >= 0)
  2386. X    close(fd);
  2387. X    return(error);
  2388. X}
  2389. X
  2390. X
  2391. XWriteHeader(c, str, len)
  2392. Xchar c;
  2393. Xchar *str;
  2394. Xlong len;
  2395. X{
  2396. X    ubyte sl;
  2397. X
  2398. X    if (str == NULL)
  2399. X    str = "";
  2400. X    sl = strlen(str);
  2401. X
  2402. X    if (gwrite(Chan, &c, 1) < 0)
  2403. X    return(1);
  2404. X    if (gwrite(Chan, &sl,1) < 0)
  2405. X    return(1);
  2406. X    if (gwrite(Chan, str, sl) != sl)
  2407. X    return(1);
  2408. X    len = htonl68(len);
  2409. X    if (gwrite(Chan, &len, 4) != 4)
  2410. X    return(1);
  2411. X    return(0);
  2412. X}
  2413. X
  2414. XReadHeader(hdr)
  2415. XHDR *hdr;
  2416. X{
  2417. X    ubyte sl;
  2418. X    ubyte cmd;
  2419. X
  2420. X    hdr->Cmd = -1;
  2421. X    if (ggread(Chan, &cmd, 1) != 1)
  2422. X    return(-1);
  2423. X    if (ggread(Chan, &sl, 1) != 1)
  2424. X    return(-1);
  2425. X    if (sl >= sizeof(hdr->Str)) {
  2426. X    return(-1);
  2427. X    }
  2428. X    if (ggread(Chan, hdr->Str, sl) != sl)
  2429. X    return(-1);
  2430. X    hdr->Str[sl] = 0;
  2431. X    if (ggread(Chan, &hdr->Val, 4) != 4)
  2432. X    return(-1);
  2433. X    hdr->Val = ntohl68(hdr->Val);
  2434. X    hdr->Cmd = cmd;
  2435. X    return(hdr->Cmd);
  2436. X}
  2437. X
  2438. Xchar *
  2439. Xgetnamepart(str)
  2440. Xchar *str;
  2441. X{
  2442. X    register char *ptr = str + strlen(str);
  2443. X
  2444. X    while (ptr >= str) {
  2445. X    if (*ptr == '/')
  2446. X        break;
  2447. X    --ptr;
  2448. X    }
  2449. X    return(ptr+1);
  2450. X}
  2451. X
  2452. Xchar *
  2453. Xgetdirpart(str)
  2454. Xchar *str;
  2455. X{
  2456. X    static char buf[1024];
  2457. X
  2458. X    strcpy(buf, str);
  2459. X    getnamepart(buf)[0] = 0;
  2460. X    if (buf[0] == 0)
  2461. X    return(".");
  2462. X    return(buf);
  2463. X}
  2464. END_OF_FILE
  2465. if test 5462 -ne `wc -c <'unix/server/sgcopy.c'`; then
  2466.     echo shar: \"'unix/server/sgcopy.c'\" unpacked with wrong size!
  2467. fi
  2468. # end of 'unix/server/sgcopy.c'
  2469. fi
  2470. echo shar: End of archive 3 \(of 8\).
  2471. cp /dev/null ark3isdone
  2472. MISSING=""
  2473. for I in 1 2 3 4 5 6 7 8 ; do
  2474.     if test ! -f ark${I}isdone ; then
  2475.     MISSING="${MISSING} ${I}"
  2476.     fi
  2477. done
  2478. if test "${MISSING}" = "" ; then
  2479.     echo You have unpacked all 8 archives.
  2480.     rm -f ark[1-9]isdone
  2481. else
  2482.     echo You still need to unpack the following archives:
  2483.     echo "        " ${MISSING}
  2484. fi
  2485. ##  End of shell archive.
  2486. exit 0
  2487. -- 
  2488. Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
  2489. Mail comments to the moderator at <amiga-request@cs.odu.edu>.
  2490. Post requests for sources, and general discussion to comp.sys.amiga.
  2491.